/********************************************************************************************/
/* 	\file			dev_led.c
 *	\date
 *	\author
 *	\model
 *	\description
 *	\version
 *
 *********************************************************************************************
 *	\par	Revision History:
 *	<!-----	No.		Date		Revised by		Details	------------------------------------->
 *
 ********************************************************************************************/

/********************************************************************************************/
/*							Include File Section											*/
/********************************************************************************************/
#include <string.h>
#include <stdbool.h>
#include "TypeDef.h"
#include "rtos.h"
#include "rtos_config.h"

#include "interrupt_manager.h"
#include "pit.h"
#include "pit_driver.h"
#include "pins_driver.h"

#include "dev_led.h"
/********************************************************************************************/
/*							Macro Definition Section										*/
/********************************************************************************************/
#define DEV_LED_PIT_PERIOD		(10)				/*Period(ms)*/
/********************************************************************************************/
/*							Type Definition Section											*/
/********************************************************************************************/

/********************************************************************************************/
/*							Enumeration Type Definition Section								*/
/********************************************************************************************/

/********************************************************************************************/
/*							Structure/Union Type Definition Section							*/
/********************************************************************************************/
typedef struct{
	GPIO_Type*				Type;
	uint32					Channel;
	uint32      			u32GPIO_Num;
	uint32					u32PwmChannel;
}LED_Gpio_ts;

typedef struct{
	uint32				u32Enable;			/*Enable*/
    uint32              u32Pulse;			/*Blink-->On*/
    uint32              u32Period;			/*Blink-->On+Off*/
    uint32				u32Times;			/*Blink-->Times*/
    uint32              u32Brightness;		/*Brightness*/
    uint32				u32Color;			/*Color*/
}LED_Config_ts;

typedef struct{
	uint32              u32Status;						/*On/Off*/
	uint32              u32Count;						/*Blink-->Count*/
	uint32              u32Times;						/*Blink-->Times*/
	uint32              u32Finish;						/*Blink-->Done*/
}LED_Info_ts;

typedef struct{
    int32               i32Status;          			/*Close/Open*/
    LED_Config_ts		stConfigUser[LED_ID_MAX];		/*UserConfig*/
    LED_Config_ts		stConfigLocal[LED_ID_MAX];		/*LocalConfig*/
    LED_Info_ts			stInfo[LED_ID_MAX];				/*Info*/
    //void     			(*pvdCallback)(void); 			/*Callback*/
}LED_Var_ts;

/********************************************************************************************/
/*							Global Variable Definition Section								*/
/********************************************************************************************/

/********************************************************************************************/
/*							Static Variable Definition Section								*/
/********************************************************************************************/
static LED_Var_ts stDevLed_Var;

static const LED_Gpio_ts stLED_GpioTbl[LED_ID_MAX][3]={
			/*Blue,				Green,			Red*/
/*LED1*/	{{PTF, 5, 85,0},	{PTF, 6, 86,0},	{PTF, 7, 87,0}},
/*LED2*/	{{PTE, 0, 64,0},	{PTE, 9, 73,0},	{PTJ, 3,147,0}},
/*LED3*/	{{PTJ, 1,145,0},	{PTJ, 2,146,0},	{PTC, 7, 39,0}},
/*LED4*/	{{PTJ, 0,144,0},	{PTD,13, 61,0},	{PTE, 3, 67,0}}
};

static const uint32 u32ColorTbl[LED_COLOR_MAX][3]={
			/*Blue,			Green,			Red*/
/*BLACK*/	{FALSE,			FALSE,			FALSE},		/*CloseAll*/
/*YELLOW*/	{FALSE,			TRUE,			TRUE},
/*GREEN*/	{FALSE,			TRUE,			FALSE},
/*RED*/		{FALSE,			FALSE,			TRUE},
/*WHITE*/	{TRUE,			TRUE,			TRUE}
};
/********************************************************************************************/
/*							Static Prototype Declaration Section							*/
/********************************************************************************************/
static void vdLedPitCallback(void);
static void vdLedDevice_SetColor(LED_ID_Enum_t ID,LED_Color_Enum_t Color);
/********************************************************************************************/
/*							ROM Table Section												*/
/********************************************************************************************/

static const LED_Config_ts stLedConfigDefault[LED_ID_MAX]={
		/*Enable,	Pulse,	Period,	Times,	Brightness,	Color*/
/*LED1*/{TRUE,		500,	1000,	10,		100,		YELLOW},
/*LED2*/{TRUE,		500,	1000,	20,		100,		GREEN},
/*LED3*/{TRUE,		500,	1000,	50,		100,		RED},
/*LED4*/{TRUE,		1000,	1000,	0,	    100,		WHITE},
};
/********************************************************************************************/
/*							Function Definition Section										*/
/********************************************************************************************/

void vdLedDevice_Init(void){
	memset(&stDevLed_Var,0,sizeof(stDevLed_Var));
	memcpy(stDevLed_Var.stConfigUser,stLedConfigDefault,sizeof(LED_Config_ts) * LED_ID_MAX);
    PIT_DRV_InitChannel(INST_PIT,&LED_Driver_Cfg);
    INT_SYS_InstallHandler(PIT_Ch4_IRQn,(isr_t)vdLedPitCallback,0);
    INT_SYS_SetPriority(PIT_Ch4_IRQn, 8);

    stDevLed_Var.i32Status = TRUE;
    PIT_DRV_StartChannel(INST_PIT,LED_Driver_Cfg.hwChannel);
}

int32 i32LedDevice_Config(LED_ID_Enum_t ID, LED_Color_Enum_t Color, uint8 BlinkEn, uint32 BlinkTimes){
	int32 i32Rtn = RTOS_ERR_NONE;
	if(BlinkEn){
		stDevLed_Var.stConfigUser[ID].u32Enable = TRUE;
		stDevLed_Var.stConfigUser[ID].u32Color = Color;
		stDevLed_Var.stConfigUser[ID].u32Period = 1000;
		stDevLed_Var.stConfigUser[ID].u32Pulse = 500;
		stDevLed_Var.stConfigUser[ID].u32Times = BlinkTimes;
		stDevLed_Var.stInfo[ID].u32Status = FALSE;
		stDevLed_Var.stInfo[ID].u32Count = 0;
		stDevLed_Var.stInfo[ID].u32Times = 0;
		stDevLed_Var.stInfo[ID].u32Finish = 0;
	}
	else{
		stDevLed_Var.stConfigUser[ID].u32Enable = TRUE;
		stDevLed_Var.stConfigUser[ID].u32Color = Color;
		stDevLed_Var.stConfigUser[ID].u32Period = 1000;
		stDevLed_Var.stConfigUser[ID].u32Pulse = 1000;
		stDevLed_Var.stConfigUser[ID].u32Times = 0;
		stDevLed_Var.stInfo[ID].u32Status = FALSE;
		stDevLed_Var.stInfo[ID].u32Count = 0;
		stDevLed_Var.stInfo[ID].u32Times = 0;
		stDevLed_Var.stInfo[ID].u32Finish = 0;
	}

	return i32Rtn;
}

static void vdLedDevice_Loop(void){
	LED_ID_Enum_t LedID;
	if(stDevLed_Var.i32Status == TRUE){
		for(LedID = 0;LedID < LED_ID_MAX;LedID++){
			if((stDevLed_Var.stInfo[LedID].u32Count == 0)||(stDevLed_Var.stInfo[LedID].u32Count == 1)){
				//TODO:/*UpdateConfig(Sync)*/
				memcpy(&(stDevLed_Var.stConfigLocal[LedID]),&(stDevLed_Var.stConfigUser[LedID]),sizeof(LED_Config_ts));
			}
			if((stDevLed_Var.stConfigLocal[LedID].u32Enable == TRUE)
			&&(stDevLed_Var.stConfigLocal[LedID].u32Period != 0)
			&&(stDevLed_Var.stConfigLocal[LedID].u32Period >= stDevLed_Var.stConfigLocal[LedID].u32Pulse)
			&&(stDevLed_Var.stConfigLocal[LedID].u32Brightness > 0)
			&&(stDevLed_Var.stInfo[LedID].u32Finish == 0)){
				if(stDevLed_Var.stInfo[LedID].u32Count == 0){
					stDevLed_Var.stInfo[LedID].u32Count += DEV_LED_PIT_PERIOD;
					if(stDevLed_Var.stInfo[LedID].u32Status == FALSE){
						/*LedOn*/
						vdLedDevice_SetColor((LED_ID_Enum_t)LedID,(LED_Color_Enum_t)(stDevLed_Var.stConfigLocal[LedID].u32Color));
						stDevLed_Var.stInfo[LedID].u32Status = TRUE;
					}
				}
				else if((stDevLed_Var.stInfo[LedID].u32Count >= stDevLed_Var.stConfigLocal[LedID].u32Pulse)
						&&(stDevLed_Var.stConfigLocal[LedID].u32Pulse != stDevLed_Var.stConfigLocal[LedID].u32Period)){
					stDevLed_Var.stInfo[LedID].u32Count += DEV_LED_PIT_PERIOD;
					if(stDevLed_Var.stInfo[LedID].u32Status == TRUE){
						/*LedOff*/
						vdLedDevice_SetColor((LED_ID_Enum_t)LedID,(LED_Color_Enum_t)(BLACK));
						stDevLed_Var.stInfo[LedID].u32Status = FALSE;
					}
				}
				else if((stDevLed_Var.stInfo[LedID].u32Count == stDevLed_Var.stConfigLocal[LedID].u32Pulse)
						&&(stDevLed_Var.stConfigLocal[LedID].u32Pulse == stDevLed_Var.stConfigLocal[LedID].u32Period)){
					stDevLed_Var.stInfo[LedID].u32Count += DEV_LED_PIT_PERIOD;
				}
				else if(stDevLed_Var.stInfo[LedID].u32Count >= stDevLed_Var.stConfigLocal[LedID].u32Period){
					stDevLed_Var.stInfo[LedID].u32Count = DEV_LED_PIT_PERIOD;
					if(stDevLed_Var.stConfigLocal[LedID].u32Pulse != stDevLed_Var.stConfigLocal[LedID].u32Period){
						if(stDevLed_Var.stInfo[LedID].u32Status == FALSE){
							/*LedOn*/
							vdLedDevice_SetColor((LED_ID_Enum_t)LedID,(LED_Color_Enum_t)(stDevLed_Var.stConfigLocal[LedID].u32Color));
							stDevLed_Var.stInfo[LedID].u32Status = TRUE;
						}

						if(stDevLed_Var.stConfigLocal[LedID].u32Times != 0){
							stDevLed_Var.stInfo[LedID].u32Times++;
							if(stDevLed_Var.stInfo[LedID].u32Times >= stDevLed_Var.stConfigLocal[LedID].u32Times){
								/*LedOff(BlinkFinish)*/
								stDevLed_Var.stInfo[LedID].u32Times = 0;
								vdLedDevice_SetColor((LED_ID_Enum_t)LedID,(LED_Color_Enum_t)(BLACK));
								stDevLed_Var.stInfo[LedID].u32Status = FALSE;
								stDevLed_Var.stInfo[LedID].u32Finish = TRUE;
							}
						}
					}
					else if(stDevLed_Var.stConfigLocal[LedID].u32Pulse == stDevLed_Var.stConfigLocal[LedID].u32Period){

					}
					else{

					}
				}
				else{
					stDevLed_Var.stInfo[LedID].u32Count += DEV_LED_PIT_PERIOD;
				}
			}
		}
	}
}

static void vdLedDevice_SetColor(LED_ID_Enum_t ID,LED_Color_Enum_t Color){
	PINS_DRV_WritePin(stLED_GpioTbl[ID][0].Type,(pins_channel_type_t)(stLED_GpioTbl[ID][0].Channel),(pins_level_type_t)(u32ColorTbl[Color][0]));
	PINS_DRV_WritePin(stLED_GpioTbl[ID][1].Type,(pins_channel_type_t)(stLED_GpioTbl[ID][1].Channel),(pins_level_type_t)(u32ColorTbl[Color][1]));
	PINS_DRV_WritePin(stLED_GpioTbl[ID][2].Type,(pins_channel_type_t)(stLED_GpioTbl[ID][2].Channel),(pins_level_type_t)(u32ColorTbl[Color][2]));
}


static void vdLedPitCallback(void){
	PIT_DRV_ClearStatusFlags(INST_PIT,LED_Driver_Cfg.hwChannel);
	vdLedDevice_Loop();
	//portNOP();
}





